<?php
/**
 * 【超人】模块定义
 *
 * @author 超人
 * @url
 */
defined('IN_IA') or exit('Access Denied');
class SupermanTestUtil {
    public static function formatTime ($timestamp) {
        $time_diff = (TIMESTAMP - $timestamp)/60;
        if($time_diff <= 1) {
            $format = '1分钟';
        } else if ($time_diff > 1 && $time_diff < 60) {
            $format = floor($time_diff).'分钟';
        } else if ($time_diff >= 60 && $time_diff < 1440) {
            $format = floor($time_diff/60).'小时';
        } else if ($time_diff >= 1440 && $time_diff < 43200) {
            $format = floor($time_diff/1440).'天';
        } else if ($time_diff >= 43200 && $time_diff < 518400) {
            $format = floor($time_diff/43200).'月';
        } else {
            $format = floor($time_diff/518400).'年';
        }
        return $format;
    }
    public static function json($errno, $errmsg = '', $data = array()) {
        ob_end_clean();
        if ($errmsg == '') {
            $errmsg = SupermanErrno::$ERRMSG[$errno];
        }
        $result = array(
            'errno' => $errno,
            'errmsg' => $errmsg,
            'data' => $data,
        );
        @header('Content-Type: application/json; charset=utf-8');
        exit(json_encode($result));
    }
    public static function background_running() {
        //TODO
    }
    public static function redirect($url) {
        ob_end_clean();
        @header('Location: '.$url);
        exit;
    }
    public static function weiqing_polyfill() {
        global $_GPC, $do;
        if (empty($_GPC['do'])) {
            if (isset($_GPC['eid']) && $_GPC['eid']) {
                $eid = intval($_GPC['eid']);
                $row = pdo_get('modules_bindings', array(
                    'eid' => $eid,
                ));
                if (!empty($row)) {
                    $_GPC['do'] = $row['do'];
                    $_GPC['m'] = $row['module'];
                    $do = $_GPC['do'];
                }
            }
        } else if (empty($do)) {
            $do = $_GPC['do'];
        }
    }
    public static function get_tables($module_name = '') {
        if ($module_name == '' && defined('SUPERMAN_MODULE_NAME')) {
            $module_name = SUPERMAN_MODULE_NAME;
        }
        $tables = array();
        $sql = "SHOW TABLES";
        $list = pdo_fetchall($sql);
        if (!empty($list)) {
            foreach ($list as $k=>$v) {
                $arr = array_values($v);
                $tablename = $arr[0];
                if (strpos($tablename, $module_name) !== false) {
                    $tables[] = $tablename;
                }
            }
        }
        return $tables;
    }
    public static function format_date($str) {
        return substr($str, 0, 4).'-'.substr($str, 4, 2).'-'.substr($str, 6, 2);
    }
    public static function float_format($num, $len = 2) {
        $multiplier = pow(10, $len);
        $arr = explode('.', $num * $multiplier);
        $result = $arr[0]/$multiplier;
        return sprintf('%.'.$len.'f', $result);
    }
    public static function weaccount_create() {
        global $_W;
        static $account = null;
        if (!is_null($account)) {
            return $account;
        }
        if (empty($_W['account'])) {
            if (isset($_W['uniacid']) && $_W['uniacid']) {
                $_W['account'] = uni_fetch($_W['uniacid']);
            } else if (isset($_W['acid']) && $_W['acid']) {
                $_W['account'] = account_fetch($_W['acid']);
            } else {
                SupermanTestUtil::logging('fatal', '[weaccount_create]初始化失败，缺少acid||uniacid参数');
                return error(-1, '初始化失败，缺少acid||uniacid参数');
            }
        }
        if ($_W['account']['level'] < 3) {
            SupermanTestUtil::logging('fatal', '[weaccount_create]公众号没有经过认证');
            return error(-1, '公众号没有经过认证');
        }
        $account = WeAccount::create();
        if (is_null($account)) {
            SupermanTestUtil::logging('fatal', '[weaccount_create]创建公众号操作对象失败');
            return error(-1, '创建公众号操作对象失败');
        }
        return $account;
    }
    public static function send_tmplmsg($data, $openid, $tpl_id, $url) {
        global $_W;
        //$_W['account']参数存在为空的情况，必须先初始化
        $account = self::weaccount_create();
        if ($_W['account']['level'] != 4) { //服务号（已认证）
            SupermanTestUtil::logging("fatal", "[send_tmplmsg] 模板消息发送失败：非认证服务号没有发送模板消息权限");
            return false;
        }
        if (!$openid) {
            SupermanTestUtil::logging("fatal", "[send_tmplmsg] 模板消息发送失败：openid为空");
            return false;
        }
        if (empty($tpl_id)) {
            SupermanTestUtil::logging("fatal", "[send_tmplmsg] 模板消息发送失败：未配置模版消息");
            return false;
        }
        $ret = $account->sendTplNotice($openid, $tpl_id, $data, $url);
        if ($ret !== true) {
            SupermanTestUtil::logging("fatal", "[send_tmplmsg] 模板消息发送失败：openid={$openid}, ret=".var_export($ret, true).", message=" . var_export($data, true));
            if (strpos($ret['message'], '40001') || strpos($ret['message'], '42001')) {
                $account->sendTplNotice($openid, $tpl_id, $data, $url);
            }
        } else {
            SupermanTestUtil::logging("info", "[send_tmplmsg] 模板消息发送成功：openid={$openid}, message=" . var_export($data, true));
        }

    }
    //模板消息
    public static function wxapp_send_tmplmsg($type, $template, $openid, $form_id, $data, $url = '') {
        global $_W;
        if (!in_array($type, array('submit', 'pay', 'send', 'cancel', 'refund'))) {
            SupermanTestUtil::logging('fatal', '[wxapp_template_message] 非法参数，type='.$type);
            return false;
        }
        if (!$openid) {
            SupermanTestUtil::logging('fatal', '[wxapp_template_message] 非法参数，openid is null');
            return false;
        }
        $post = array(
            'touser' => $openid,
            'template_id' => $template[$type]['tmpl_id'],
            'page' => $url,
            'form_id' => $form_id,    //表单提交场景下，为 submit 事件带上的 formId；支付场景下，为本次支付的 prepay_id
            'data' => $data,
        );
        $account = WeAccount::create();
        $exit = false;
        do {
            $token = $account->getAccessToken();
            if (is_error($token)) {
                SupermanTestUtil::logging('fatal', '[superman_tuan:wxapp_template_message]get access_token fail, appid='.$_W['account']['key'].', appsecret='.$_W['account']['secret'].', errmsg='.$token['message']);
                break;
            }
            $post_url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' . $token;
            $response = ihttp_request($post_url, json_encode($post));
            $result = @json_decode($response['content'], true);
            if (is_error($response)) {
                SupermanTestUtil::logging('fatal', '[wxapp_template_message]访问公众平台接口失败, 错误详情: '.SupermanTestUtil::wxapp_error_code($result['errcode']).', appid='.$_W['account']['key'].', secret='.$_W['account']['secret'].', post='.var_export($post, true));
                break;
            }
            if (empty($result)) {
                SupermanTestUtil::logging('fatal', '[wxapp_template_message] 接口调用失败, 元数据: '.$response['meta'].', appid='.$_W['account']['key']);
                break;
            } else if (!empty($result['errcode'])) {
                if ($result['errcode'] == '40001') { // token过期重新发送
                    $exit = true;
                    continue;
                }
                SupermanTestUtil::logging('fatal', "[wxapp_template_message] 访问公众平台接口失败, 错误: {$result['errmsg']}");
                break;
            }
        } while ($exit);
        return $result;
    }
    public static function wxapp_custom_notice($data) {
        global $_W;
        $exit = false;
        $account = WeAccount::create();
        do {
            $token = $account->getAccessToken();
            if (is_error($token)) {
                SupermanTestUtil::logging('fatal', '[superman_tuan:wxapp_template_message]get access_token fail, appid='.$_W['account']['key'].', appsecret='.$_W['account']['secret'].', errmsg='.$token['message']);
                break;
            }
            $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={$token}";
            $response = ihttp_request($url, urldecode(json_encode($data)));
            if(is_error($response)) {
                SupermanTestUtil::logging('fatal', "访问公众平台接口失败, 错误: {$response['message']}");
                break;
            }
            $result = @json_decode($response['content'], true);
            if(empty($result)) {
                SupermanTestUtil::logging('fatal', "接口调用失败, 元数据: {$response['meta']}");
                break;
            } elseif(!empty($result['errcode'])) {
                if ($result['errcode'] == '40001') { // token过期重新发送
                    $exit = true;
                    continue;
                }
                SupermanTestUtil::logging('fatal', "访问微信接口错误, 错误代码: {$result['errcode']}, 错误信息: {$result['errmsg']},错误详情：".SupermanTestUtil::wxapp_error_code($result['errcode']));
                break;
            }
        } while ($exit);
        return $result;
    }
    public static function wxapp_error_code($code, $errmsg = '未知错误') {
        $errors = array(
            '-1' => '系统繁忙',
            '0' => '请求成功',
            '40001' => '获取access_token时AppSecret错误，或者access_token无效',
            '40002' => '不合法的凭证类型',
            '40003' => '不合法的OpenID',
            '40004' => '不合法的媒体文件类型',
            '40005' => '不合法的文件类型',
            '40006' => '不合法的文件大小',
            '40007' => '不合法的媒体文件id',
            '40008' => '不合法的消息类型',
            '40009' => '不合法的图片文件大小',
            '40010' => '不合法的语音文件大小',
            '40011' => '不合法的视频文件大小',
            '40012' => '不合法的缩略图文件大小',
            '40013' => '不合法的APPID',
            '40014' => '不合法的access_token',
            '40015' => '不合法的菜单类型',
            '40016' => '不合法的按钮个数',
            '40017' => '不合法的按钮个数',
            '40018' => '不合法的按钮名字长度',
            '40019' => '不合法的按钮KEY长度',
            '40020' => '不合法的按钮URL长度',
            '40021' => '不合法的菜单版本号',
            '40022' => '不合法的子菜单级数',
            '40023' => '不合法的子菜单按钮个数',
            '40024' => '不合法的子菜单按钮类型',
            '40025' => '不合法的子菜单按钮名字长度',
            '40026' => '不合法的子菜单按钮KEY长度',
            '40027' => '不合法的子菜单按钮URL长度',
            '40028' => '不合法的自定义菜单使用用户',
            '40029' => '不合法的oauth_code',
            '40030' => '不合法的refresh_token',
            '40031' => '不合法的openid列表',
            '40032' => '不合法的openid列表长度',
            '40033' => '不合法的请求字符，不能包含\uxxxx格式的字符',
            '40035' => '不合法的参数',
            '40038' => '不合法的请求格式',
            '40039' => '不合法的URL长度',
            '40050' => '不合法的分组id',
            '40051' => '分组名字不合法',
            '41001' => '缺少access_token参数',
            '41002' => '缺少appid参数',
            '41003' => '缺少refresh_token参数',
            '41004' => '缺少secret参数',
            '41005' => '缺少多媒体文件数据',
            '41006' => '缺少media_id参数',
            '41007' => '缺少子菜单数据',
            '41008' => '缺少oauth code',
            '41009' => '缺少openid',
            '42001' => 'access_token超时',
            '42002' => 'refresh_token超时',
            '42003' => 'oauth_code超时',
            '43001' => '需要GET请求',
            '43002' => '需要POST请求',
            '43003' => '需要HTTPS请求',
            '43004' => '需要接收者关注',
            '43005' => '需要好友关系',
            '44001' => '多媒体文件为空',
            '44002' => 'POST的数据包为空',
            '44003' => '图文消息内容为空',
            '44004' => '文本消息内容为空',
            '45001' => '多媒体文件大小超过限制',
            '45002' => '消息内容超过限制',
            '45003' => '标题字段超过限制',
            '45004' => '描述字段超过限制',
            '45005' => '链接字段超过限制',
            '45006' => '图片链接字段超过限制',
            '45007' => '语音播放时间超过限制',
            '45008' => '图文消息超过限制',
            '45009' => '接口调用超过限制',
            '45010' => '创建菜单个数超过限制',
            '45015' => '回复时间超过限制',
            '45016' => '系统分组，不允许修改',
            '45017' => '分组名字过长',
            '45018' => '分组数量超过上限',
            '45047' => '客服接口下行条数超过上限',
            '45056' => '创建的标签数过多，请注意不能超过100个',
            '45057' => '该标签下粉丝数超过10w，不允许直接删除',
            '45058' => '不能修改0/1/2这三个系统默认保留的标签',
            '45059' => '有粉丝身上的标签数已经超过限制',
            '45157' => '标签名非法，请注意不能和其他标签重名',
            '45158' => '标签名长度超过30个字节',
            '45159' => '非法的标签',
            '46001' => '不存在媒体数据',
            '46002' => '不存在的菜单版本',
            '46003' => '不存在的菜单数据',
            '46004' => '不存在的用户',
            '47001' => '解析JSON/XML内容错误',
            '48001' => 'api功能未授权',
            '50001' => '用户未授权该api',
            '40070' => '基本信息baseinfo中填写的库存信息SKU不合法。',
            '41011' => '必填字段不完整或不合法，参考相应接口。',
            '40056' => '无效code，请确认code长度在20个字符以内，且处于非异常状态（转赠、删除）。',
            '43009' => '无自定义SN权限，请参考开发者必读中的流程开通权限。',
            '43010' => '无储值权限,请参考开发者必读中的流程开通权限。',
            '43011' => '无积分权限,请参考开发者必读中的流程开通权限。',
            '40078' => '无效卡券，未通过审核，已被置为失效。',
            '40079' => '基本信息base_info中填写的date_info不合法或核销卡券未到生效时间。',
            '45021' => '文本字段超过长度限制，请参考相应字段说明。',
            '40080' => '卡券扩展信息cardext不合法。',
            '40097' => '基本信息base_info中填写的参数不合法。',
            '48001' => 'api功能未授权，请确认小程序已获得该接口。',
            '49004' => '签名错误。',
            '43012' => '无自定义cell跳转外链权限，请参考开发者必读中的申请流程开通权限。',
            '40099' => '该code已被核销。',
            '61005' => '缺少接入平台关键数据，等待微信开放平台推送数据，请十分钟后再试或是检查“授权事件接收URL”是否写错（index.php?c=account&amp;a=auth&amp;do=ticket地址中的&amp;符号容易被替换成&amp;amp;）',
            '61023' => '请重新授权接入该公众号',
        );
        $code = strval($code);
        if($errors[$code]) {
            return $errors[$code];
        } else {
            return $errmsg;
        }
    }
    public static function sign($data, $sign_key) {
        ksort($data);
        $data_str = '';
        foreach ($data as $k=>$v) {
            if ($v == '' || $k == 'sign') {
                continue;
            }
            $data_str .= "$k=$v&";
        }
        $data_str .= "key=".$sign_key;
        $sign = strtoupper(md5($data_str));
        return $sign;
    }
    public static function short_url($url, $uniacid = 0, $acid = 0) {
        global $_W;
        $uniacid = !empty($uniacid)?$uniacid:$_W['uniacid'];
        $acid = !empty($acid)?$acid:$_W['acid'];
        if (defined('LOCAL_DEVELOPMENT')) {
            return $url;
        } else {
            if (in_array($_W['account']['level'], array(3, 4))) {
                if (empty($_W['account'])) {
                    if ($uniacid) {
                        $_W['account'] = uni_fetch($uniacid);
                    } else if ($acid) {
                        $_W['account'] = account_fetch($acid);
                    } else {
                        SupermanTestUtil::logging('fatal', "[short_url] failed, not found uniacid & acid");
                        return $url; //无法转换时，返回原网址
                    }
                }
                $account = WeAccount::create();
                if (is_null($account)) {
                    SupermanTestUtil::logging('fatal', "[short_url] failed, not created");
                    return $url; //无法转换时，返回原网址
                }
                if (is_error($account)) {
                    SupermanTestUtil::logging('fatal', "[short_url] failed, url={$url}, account=".var_export($account, true));
                    return $url; //无法转换时，返回原网址
                }
                $ret = $account->long2short($url);
                if (is_error($ret)) {
                    SupermanTestUtil::logging('fatal', "[short_url] failed, url={$url}, ret=".var_export($ret, true));
                    return $url; //无法转换时，返回原网址
                }
                return $ret['short_url']?$ret['short_url']:$url;
            }
            return $url; //无法转换时，返回原网址
        }
    }
    public static function logging($level = 'info', $message = '') {
        global $_W;
        $filename = MODULE_ROOT . 'logs/' . date('Ymd') . '.php';
        load()->func('file');
        $content = '';
        if (!file_exists($filename)) {
            $content .= "<?php exit;?>\n";
        }
        mkdirs(dirname($filename));
        $content .= date('Y-m-d H:i:s') . " {$level} :\n------------\n";
        if(is_string($message) && !in_array($message, array('post', 'get'))) {
            $content .= "String:\n{$message}\n";
        }
        if(is_array($message)) {
            $content .= "Array:\n";
            foreach($message as $key => $value) {
                $content .= sprintf("%s : %s ;\n", $key, $value);
            }
        }
        if($message === 'get') {
            $content .= "GET:\n";
            foreach($_GET as $key => $value) {
                $content .= sprintf("%s : %s ;\n", $key, $value);
            }
        }
        if($message === 'post') {
            $content .= "POST:\n";
            foreach($_POST as $key => $value) {
                $content .= sprintf("%s : %s ;\n", $key, $value);
            }
        }
        $content .= "\n";
        $fp = fopen($filename, 'a+');
        fwrite($fp, $content);
        fclose($fp);
    }
}